

#ifndef _FD_MAMAGER_H_
#define _FD_MAMAGER_H_


#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <cstdint>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <vector>


namespace zepco {

class Fdctx : public std::enable_shared_from_this<Fdctx> {
  private:
    bool m_isInit = false;  // fd是否已经初始化
    bool m_isSocket = false; // fd是否为一个sockfd
    bool m_sysNonBlock = false; // fd是否设置为系统非阻塞
    bool m_userNonBlock = false; // fd是否设置为用户非阻塞
    bool m_isClosed = false; // fd是否已关闭
    int m_fd;

    uint64_t m_recvTimeout = (uint64_t) -1; // 读事件超时时间
    uint64_t m_sendTimeout = (uint64_t) -1; // 写事件超时时间

  public:
    Fdctx(int fd);
    ~Fdctx();

    bool init();
    bool isInit() const {
        return m_isInit;
    }
    bool isSocket() const {
        return m_isSocket;
    }
    bool isClosed() const {
        return m_isClosed;
    }

    void setUserNonBlock(bool v) {
        m_userNonBlock = v;
    }

    bool getUserNonBlock() const {
        return m_userNonBlock;
    }

    void setSysNonBlock(bool v) {
        m_sysNonBlock = v;
    }

    bool getSysNonBlock() const {
        return m_sysNonBlock;
    }

    void setTimeout(int type, uint64_t v);
    uint64_t getTimeout(int type);

};


class FdManager {
  public:
    FdManager();
    // 获取指定文件描述符的fdctx对象
    std::shared_ptr<Fdctx> get(int fd, bool auto_create = false);
    // 删除指定fd的fdctx对象
    void del(int fd);
  private:
    std::shared_mutex m_mtx; // 共享读锁 独占写锁
    std::vector<std::shared_ptr<Fdctx>> m_datas;
};

template<typename T>
class Singleton {
public:
    static T *GetInstance() {
        std::lock_guard<std::mutex> lock(mutex);
        if (instance == nullptr) {
            instance = new T();
        }
        return instance;
    }
    static void DestoryInstance() {
        std::lock_guard<std::mutex> lock(mutex);
        if (instance) {
            delete instance;
            instance = nullptr;
        }
    }
  private:
    Singleton();
    ~Singleton();
    Singleton(const Singleton &) = delete;
    Singleton &operator=(const Singleton &) = delete;

  private:
    static T *instance;
    static std::mutex mutex;
};

template class Singleton<FdManager>;
template<typename T>
T *Singleton<T>::instance = nullptr;
template<typename T>
std::mutex Singleton<T>::mutex;

typedef Singleton<FdManager> FdMgr;

}

#endif // _FD_MAMAGER_H_